feat(dialtone-cli,dialtone-query-core): DLT-3163 extract query core and add CLI#1142
Conversation
…nd add CLI Extract search logic from dialtone-mcp-server into a shared dialtone-query-core package. Create dialtone-cli as a token-efficient terminal interface to the same search engine. - dialtone-query-core: types, search functions, filters, data loading - dialtone-cli: search, component, token, utility, prompt commands - dialtone-mcp-server: refactored to import from query-core - HSL decomposition tokens filtered from search results by default - Component search now handles camelCase queries (DtButton works) - OR search support via pipe separator (input|select|menu)
Wiz Scan Summary
To detect these findings earlier in the dev lifecycle, try using Wiz Code VS Code Extension. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5bcb9b6c5a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "Codex (@codex) review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".
CLI now resolves data from the project's installed Dialtone packages (via Node module resolution) before falling back to bundled data. This ensures search results match the project's pinned version. - Uses createRequire rooted at cwd for pnpm/npm/workspace compat - Shows "Using local Dialtone data (vX.Y.Z)" on stderr when detected - --bundled flag forces use of CLI's built-in data
Fix data resolver to use the correct export-mapped specifiers for the @dialpad/dialtone umbrella package (css/* not dist/css/*). Tested against beacon-app (next) and firespotter (stable).
| * "DtButton" → ["Dt", "Button"] | ||
| */ | ||
| function splitCamelCase(name: string): string[] { | ||
| return name.replace(/([A-Z])/g, ' $1').trim().split(' ').map(w => w.toLowerCase()); |
There was a problem hiding this comment.
This gives 'D t B utton'. So a name-bucket search for "button" against DtButton won't match.
There was a problem hiding this comment.
Verified — splitCamelCase("DtButton") actually returns ["dt", "button"], not ["d", "t", "b", "utton"]. The regex ([A-Z]) inserts a space before each uppercase letter, but consecutive lowercase letters stay grouped: " Dt Button" → trim → split → ["Dt", "Button"].
It would break on consecutive uppercase like DtRTE → ["dt", "r", "t", "e"], but we don't have component names like that in the library.
- silence-debug: use explicit core debug prefix allowlist instead of blanket [* match that swallowed Node warnings - HSL filter: scope regex to color tokens only (--dt-*color*-h/s/l/a) - prompt formatter: split on sentence boundaries (period + uppercase) instead of any period + space, avoiding e.g./i.e. false splits
There was a problem hiding this comment.
I guess the main question I have here, is does dialtone-query-core need to be a "package"? I think it would depend on what we are planning on doing with it in the future, but right now it's basically just a library of functions that are not intended for external use and are only used internally. It has it's own package.json / project.json / ci config etc which are all really only necessary for externally consumed packages. The way it is being used now, we could just as easily add a new directory called dialtone_query_core in dialtone/common and it would be a whole lot simpler to just import from that folder in both projects. Wouldn't have to worry about package dependencies or the release pipeline or anything.
There was a problem hiding this comment.
Fair point. The core is internal-only right now and a common/ folder would eliminate the package.json, project.json, release config, and the workspace dependency ceremony.
The trade-off is build orchestration. As a package, NX handles the build ordering automatically (dependsOn: ["dialtone-query-core:build"]), and both consumers resolve it cleanly via workspace:*. Moving to common/ means:
- Each consumer's tsconfig needs to include
common/in its compilation scope - Rollup configs need relative path aliases instead of package resolution
- NX build ordering becomes implicit (no
dependsOn, just hope the files are there)
None of that is hard, but it's swapping one kind of config for another. If the team prefers common/, happy to move it — it's a straightforward refactor. The search logic and API surface don't change either way.
There was a problem hiding this comment.
Yeah it's a good point about the nx build ordering. I think we should keep it the way it is, maybe we can remove the release-ci.config.cjs and the publish and release targets from project.json so it's clear it's not releaseable.
…table3 Addresses review feedback: duplicate code, identical variables, and iteration order concerns all resolved by replacing the custom borderedTable function with cli-table3. Also adds word-wrap for long descriptions and values.
Brad Paugh (braddialpad)
left a comment
There was a problem hiding this comment.
Looks good, let's potentially remove the "release" config from dialtone-query-core before merging
dialtone-query-core is internal-only — it's bundled into dialtone-mcp-server and dialtone-cli at build time, never published independently. Remove the release pipeline and publish targets per review feedback.
# [1.3.0-next.2](dialtone-mcp-server/v1.3.0-next.1...dialtone-mcp-server/v1.3.0-next.2) (2026-03-25) ### Features * **Dialtone Cli,dialtone Query Core:** DLT-3163 extract query core and add CLI ([#1142](#1142)) ([65090e6](65090e6))
# [9.176.0-next.1](dialtone/v9.175.2...dialtone/v9.176.0-next.1) (2026-03-25) ### Bug Fixes * **Doc:** NO-JIRA correct font size utility json ([#1015](#1015)) ([76cf0fa](76cf0fa)) * **Editor:** NO-JIRA remove extra blank line in editor.mdx ([18c47ef](18c47ef)) * possible merge issue in sidebarItem.vue ([5e2e91b](5e2e91b)) * **Rich Text Editor:** DLT-3190 replace custom JSON-to-markdown converter with @tiptap/static-renderer ([#1148](#1148)) ([9629c70](9629c70)) * **Stylelint:** disable hue-degree-notation rule and update OKLCH color syntax ([81f886e](81f886e)) * **Stylelint:** disable hue-degree-notation rule and update OKLCH color syntax ([8721f43](8721f43)) * **Tokens:** DLT-3053 preserve root font size variable as reference ([#1093](#1093)) ([112ab4b](112ab4b)) * **Tokens:** handle multi-layer box shadows correctly in postcss plugin ([feea7f1](feea7f1)) * **Tokens:** NO-JIRA output line-height as unitless instead of percentages ([#1040](#1040)) ([33d8505](33d8505)) * **Tokens:** wrap css math expressions with calc() in layered build ([#966](#966)) ([1635f61](1635f61)) * update @dialpad/i18n dependencies to latest versions ([7a4b777](7a4b777)) ### Code Refactoring * **Combobox Multi Select:** NO-JIRA use logical css properties ([#1104](#1104)) ([a675daf](a675daf)) * **Components,recipes:** DLT-3043 DLT-3046 logical start/end naming with deprecated backward-compatible fallbacks ([#1079](#1079)) ([1d26a4e](1d26a4e)) * **Css:** DLT-1876 css logical properties ([#872](#872)) ([1acd6c9](1acd6c9)) * **Style:** DLT-3014 wrap all styles in css cascade layers ([#1061](#1061)) ([f8b3fed](f8b3fed)) * **Text:** DLT-2883 rename headline sizes from xxl => 2xl, etc ([#1029](#1029)) ([0ac86f3](0ac86f3)) * **Tokens,css,link,text,breadcrumbs,input Group,split Button:** tokens, CSS foundation, deprecations, tooling DLT-3011 DLT-2961 DLT-3068 DLT-3069 DLT-3070 DLT-3071 DLT-3072 ([#1092](#1092)) ([7783090](7783090)) * **Tokens:** DLT-2884 deprecate space tokens in favor of size tokens ([#1013](#1013)) ([63f6d2f](63f6d2f)) * **Tokens:** DLT-3013 convert color system from HSL to OKLCH ([#1060](#1060)) ([42dc418](42dc418)) ### Documentation * **Components:** DLT-3178 DLT-3182 unify code examples into single code-example component ([#1147](#1147)) ([d0b6e14](d0b6e14)) * DLT-1510 DLT-1511 DLT-1512 site redesign and ia ([#968](#968)) ([6ea7eb9](6ea7eb9)) * DLT-2908 ui kits landing page ([#1049](#1049)) ([d805b9d](d805b9d)) * **Editor:** DLT-3050 updated editor docs with recent changes ([#1139](#1139)) ([04bfabb](04bfabb)) * **Icons:** DLT-3220 update contributing and add claude rules and skill ([#1151](#1151)) ([296a83d](296a83d)) * NO-JIRA fix focus left-nav items on keypress down up ([#1106](#1106)) ([882c9b9](882c9b9)) * **Playground:** DLT-3119 refine playground UI and integrate across doc site ([#1127](#1127)) ([ba6b599](ba6b599)) ### Features * **Avatar:** DLT-2942 updated avatar component ([#1047](#1047)) ([e50563d](e50563d)) * **Banner, Notice, Toast, Breadcrumbs, Checkbox, Radio, Input, Select Menu, Empty State:** visual refresh, dt-text integration, form api parity DLT-2944 DLT-2945 DLT-2949 DLT-2959 DLT-2960 DLT-2957 ([#1091](#1091)) ([16e908a](16e908a)) * **Button,tabs,split Button:** visual refresh and slot updates DLT-2946 DLT-2947 DLT-2965 ([#1090](#1090)) ([ffdd56f](ffdd56f)) * **Css Utility:** DLT-2715 add default color for border css utilities ([#874](#874)) ([71310ab](71310ab)) * **Dialtone Cli,dialtone Query Core:** DLT-3163 extract query core and add CLI ([#1142](#1142)) ([65090e6](65090e6)) * **Filter Pill:** DLT-2704 create component ([#473](#473)) ([6267445](6267445)) * **Filter Pill:** DLT-2941 DtFilterPill improvements ([#1110](#1110)) ([23c5689](23c5689)) * **Icons:** DLT-3219 align star/sparkle icons with dp brand star ([#1152](#1152)) ([ef39afc](ef39afc)) * **Link,button:** DLT-3012 add underline prop ([#1059](#1059)) ([1cb91ea](1cb91ea)) * **Mode Directive, Mode Island:** DLT-3067 DLT-3078 DLT-3077 add `v-dt-mode` directive ([#1109](#1109)) ([f97efca](f97efca)) * **Segmented Control:** DLT-413 new component ([#1144](#1144)) ([ad4c6c3](ad4c6c3)) * **Style:** DLT-2976 update underline thickness and offset ([#1058](#1058)) ([1e56947](1e56947)) * **Tabs:** DLT-3114 add vertical orientation variant ([#1120](#1120)) ([3290a23](3290a23)) * **Tabs:** DLT-3162 add spread prop for horizontal distribution ([#1135](#1135)) ([6e7cd04](6e7cd04)) * **Text:** export text component from dialtone-vue ([757fdb7](757fdb7)) * **Text:** new vue component DLT-2864 DLT-2863 DLT-2862 ([#995](#995)) ([196ef8a](196ef8a)) * **Tokens:** DLT-1977 add high contrast design tokens and theme ([#938](#938)) ([a1c0457](a1c0457)) * **Tokens:** DLT-2767 exploratory shell themes ([#909](#909)) ([3afcf63](3afcf63)) * **Tokens:** DLT-2781 create color-assistive themes ([#921](#921)) ([a6cc397](a6cc397)) * **Tokens:** DLT-2802 DLT-2563 layered theming system and mode island component ([#945](#945)) ([5c72c6c](5c72c6c)) * **Tokens:** DLT-2937 introduce spacing and layout token systems ([#1045](#1045)) ([de23e12](de23e12)) * **Tokens:** update color ramps and consumer color migration tools DLT-3004 DLT-3005 DLT-3006 DLT-3007 DLT-3008 ([#1054](#1054)) ([28cb1de](28cb1de)) * **Typography, Tokens:** DLT-2856 DLT-2857 next typography system ([#994](#994)) ([d744e97](d744e97))
# [1.3.0](dialtone-mcp-server/v1.2.1...dialtone-mcp-server/v1.3.0) (2026-03-31) ### Features * **Dialtone Cli,dialtone Query Core:** DLT-3163 extract query core and add CLI ([#1142](#1142)) ([65090e6](65090e6))
# [9.176.0](dialtone/v9.175.2...dialtone/v9.176.0) (2026-03-31) ### Bug Fixes * **Rich Text Editor:** DLT-3190 replace custom JSON-to-markdown converter with @tiptap/static-renderer ([#1148](#1148)) ([9629c70](9629c70)) ### Documentation * DLT-3151 blog post for ui-kits migration and script ([#1156](#1156)) ([069ad3c](069ad3c)) * **Editor:** DLT-3050 updated editor docs with recent changes ([#1139](#1139)) ([04bfabb](04bfabb)) * **Icons:** DLT-3220 update contributing and add claude rules and skill ([#1151](#1151)) ([296a83d](296a83d)) ### Features * **Dialtone Cli,dialtone Query Core:** DLT-3163 extract query core and add CLI ([#1142](#1142)) ([65090e6](65090e6)) * DLT-3049 add code review rules, skill, agent, and command ([#1154](#1154)) ([6bdef46](6bdef46)) * **Icons:** DLT-3219 align star/sparkle icons with dp brand star ([#1152](#1152)) ([ef39afc](ef39afc))
Obligatory GIF (super important!)
🛠️ Type Of Change
📖 Jira Ticket
DLT-3163
📖 Description
Extracts the search engine from
dialtone-mcp-serverinto a shareddialtone-query-corepackage, then builds a newdialtone-clion top of it.New packages:
@dialpad/dialtone-query-core— shared search engine (types, search functions, filters, data loading). Built with tsc, consumed by both MCP server and CLI.@dialpad/dialtone-cli— terminal interface for searching components, tokens, utility classes, and icons. Built with rollup + citty.Refactored:
@dialpad/dialtone-mcp-server— now imports fromdialtone-query-coreinstead of owning the search logic. All existing behavior preserved (99% test pass rate unchanged).CLI commands:
dialtone search <query>|for ORdialtone component <name>--props,--prop <name>,--events,--slots,--describedialtone token <query>--values,--allfor HSLdialtone utility <query>dialtone prompt <name>All commands support
--format minimal(default),--format markdown,--format json, and--limit.💡 Context
The CLI exists as a token-efficient complement to the MCP server for AI agent workflows. MCP returns JSON over a protocol layer that costs context window tokens. The CLI returns plain text — same data, fewer tokens. Install both: CLI for fast lookups, MCP for deep exploration via resources.
Search improvements (in core, affects both CLI and MCP):
--all/{ includeHsl: true }to include them.DtButtonresolves correctly).input|select|menu).📦 Cross-Package Impact
dialtone-query-coredialtone-mcp-serverdialtone-clipnpm dialtoneor global installpackage.json@dialpad/dialtone-clidependencydialtonebin available in monorepoDependency flow: tokens → CSS → Vue → query-core → MCP server / CLI
📝 Checklist
For all PRs:
🔮 Next Steps
@dialpad/dialtone-query-coreand@dialpad/dialtone-clito npmdialtone-query-coredialtoneanddialtone-mcp-serverbins to root@dialpad/dialtonepackage